﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

using log4net;

namespace JsonServer.Data
{
    public static class JsonDataTableConverter
    {
        #region Logging
        static readonly ILog _log = LogManager.GetLogger(typeof(JsonDataTableConverter));
        #endregion

        #region Constants

        #endregion

        #region DateTime

        public static DateTime UNIX_EPOCH = new DateTime(2000, 1, 1, 0, 0, 0, 0);

        public static long ToUnixEpoch(this DateTime d)
        {
            long ms = (long)((d - UNIX_EPOCH).TotalMilliseconds);

            return ms;
        }
        public static DateTime FromUnixEpoch(this string d)
        {
            //var dt = DateTime.Parse(d);                   ????
            var ms = Int64.Parse(d);            // received as ms

            var dt = UNIX_EPOCH.AddMilliseconds(ms);

            return dt;
        }
        #endregion

        #region Escape
        public static string EscapeStuff(string inStr)
        {
            string escaped = inStr;

            if (string.IsNullOrEmpty(escaped))
                return escaped;

            escaped = escaped.Replace(@"\", @"\\");
            escaped = escaped.Replace("'", "\'");
// akstodo            escaped = escaped.Replace(@""", @"\""");
            escaped = escaped.Replace(@"""", @"\""");

            return escaped;
        }
        #endregion

        #region DataTable to Json

        public static string ToColumnJson(this DataTable dt)
        {
            var json = new StringBuilder();
            json.Append("{");

            // column names
            json.Append(@"""columnNames"":[");
            for (int i=0; i<dt.Columns.Count; i++)
            {
                json.AppendFormat(@"""{0}""{1}", dt.Columns[i].ColumnName, ((i >= dt.Columns.Count - 1) ? "" : ","));
            }
            json.Append("],");

            // column types
            json.Append(@"""columnTypes"":[");
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                json.AppendFormat(@"""{0}""{1}", dt.Columns[i].DataType.Name, ((i >= dt.Columns.Count - 1) ? "" : ","));
            }
            json.Append("],");

            // column data
            json.Append(@"""columnData"":[");
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                json.Append("{");

                json.AppendFormat(@"""{0}"":[", "Data" /*dt.Columns[i].ColumnName*/);

                for (int r = 0; r < dt.Rows.Count; r++)
                {
                    if (DBNull.Value == dt.Rows[r][i])
                    {
                        json.AppendFormat("null{0}", ((r >= dt.Rows.Count - 1) ? "" : ","));
                    }
                    else
                    {
                        switch (dt.Columns[i].DataType.Name)
                        {
                            case "Int16":
                            case "Int32":
                            case "Int64":
                            case "Decimal":
                            case "Float":
                            case "Double":
                                json.AppendFormat("{0}{1}", dt.Rows[r][i], ((r >= dt.Rows.Count - 1) ? "" : ","));
                                break;

                            case "Boolean":
                            case "Bool":
                                json.AppendFormat("{0}{1}", dt.Rows[r][i], ((r >= dt.Rows.Count - 1) ? "" : ","));
                                break;

                            case "string":
                            case "String":
                                json.AppendFormat(@"""{0}""{1}", EscapeStuff((string)dt.Rows[r][i]), ((r >= dt.Rows.Count - 1) ? "" : ","));
                                break;

                            case "DateTime":
                                json.AppendFormat("{0}{1}", ToUnixEpoch((DateTime)(dt.Rows[r][i])), ((r >= dt.Rows.Count - 1) ? "" : ","));
                                break;

                            default:
                                throw new NotSupportedException();
                        }
                    }
                }

                json.Append("]}");
                //json.Append("]");
                json.AppendFormat("{0}", ((i >= dt.Columns.Count - 1) ? "" : ","));
            }
            json.Append("]");

            json.Append("}");

            var data = json.ToString();
            _log.InfoFormat("Json DataTable\n{0}", data);
            return data;
        }

        public static string ToRowJson(this DataTable dt)
        {
            var json = new StringBuilder();


            return json.ToString();
        }

        #endregion

        #region Json to DataTable

        public static DataTable FromColumnJson(this string json)
        {
            return null;
        }
        public static DataTable FromRowJson(this string json)
        {
            return null;
        }

        #endregion
    }
}
